package com.tju.backend.plugin.web_socket;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.tju.backend.entity.OutWarehouseLog;
import com.tju.backend.entity.TProduct;
import com.tju.backend.entity.TStereoscopicWarehouse;
import com.tju.backend.entity.TWarehouse;
import com.tju.backend.plugin.common.GlobalCall;
import com.tju.backend.plugin.common.Push;
import com.tju.backend.utils.redis.RedisService;
import com.tju.backend.utils.result.ResultEnum;
import com.tju.backend.utils.result.ResultUtil;
import com.tju.backend.utils.tool.Constants;
import lombok.extern.slf4j.Slf4j;
import com.tju.backend.plugin.common.Const;
import org.apache.commons.lang3.StringUtils;
import org.tio.core.ChannelContext;
import org.tio.core.Tio;
import org.tio.http.common.HttpRequest;
import org.tio.http.common.HttpResponse;
import org.tio.websocket.common.WsRequest;
import org.tio.websocket.common.WsSessionContext;
import org.tio.websocket.server.handler.IWsMsgHandler;

import java.util.*;

import static com.tju.backend.plugin.common.GlobalCall.*;
import static com.tju.backend.plugin.common.GlobalCall.redisService;

/**
 * 信息处理类
 *
 * @USER: CLS
 */
@Slf4j
public class TioMsgHandler implements IWsMsgHandler {
    public static final TioMsgHandler me = new TioMsgHandler();
    public static ChannelContext channelContext = null;
    public static RedisService redis = GlobalCall.redisService;
    TStereoscopicWarehouse outSw = null;
    TStereoscopicWarehouse tsw = null;
    TStereoscopicWarehouse tStereoscopicWarehouse = null;
    List<String> list = new ArrayList<String>();
    int state = 0;
    long likuSize =0; //redis缓存数量
    private TioMsgHandler() {

    }

    public static void main(String[] args) {
        String name = "out\n" +
                "{\n" +
                "  \"msg\": \"孪生出库\",\n" +
                "  \"code\": 110,   \n" +
                "  \"data\":[1,2,3]}";
        name = StringUtils.strip(name, "out");
        RedisService redis = GlobalCall.redisService;
        JSONObject json = JSONUtil.parseObj(name);
        Object code = json.get("code");
        if (code.equals(110)) {
            String data = json.get("data").toString();
            System.err.println(data);
            data = StringUtils.strip(data, "[]");
            String[] split = data.split(",");
            for (String value : split) {
                System.err.println(value);
                if (redis.hasKey("liku")) {
                    long likuSize = redis.lGetListSize("liku");
                    for (int likuIndex = 0; likuIndex < likuSize; likuIndex++) {
                        if (value.equals(redis.lGetIndex("liku", likuIndex))) {
                            continue;
                        }
                        redis.lSet("liku", value);
                    }
                } else {
                    redis.lSet("liku", value);
                }
            }
            TStereoscopicWarehouse tStereoscopicWarehouse = sw.selectAllstatus(3);
            if (tStereoscopicWarehouse == null) {
                Integer liku = (Integer) redis.lGetIndex("liku", 0);
                redisService.lRemove("tju", 0, liku.toString());
                try {
                    TStereoscopicWarehouse tsw = sw.selectStereoscopicWarehouseById(liku);
                    Optional.ofNullable(tsw)
                            .map(l -> {
                                //修改立体库位状态
                                int rows = sw.updateStatusByBarcode(tsw.getBoxBarcode(), new Date());
                                TStereoscopicWarehouse outSw = sw.selectOne(tsw.getBoxBarcode());
                                //todo: 进行PLC发送出货
                                Push.tcpPush(GlobalCall.str(outSw));
                                //出仓
                                Push.push(ResultUtil.success(ResultEnum.OUTWAREHOUSE, GlobalCall.str(outSw)));
                                //封装参数
                                return new OutWarehouseLog(tsw, rows);
                            })
                            .filter(s -> s.getBarcode() != null)
                            .map(s -> {
                                //插入出货日志
                                outsw.insertOutWarehouseLog(s);
                                return Constants.STRING;
                            })
                            .orElseThrow(() -> new Exception(zhCh.AbnormalOrder));
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
            String lukuSize[] = new String[Math.toIntExact(redis.lGetListSize("liku"))];
            for (int likuIndex = 0; likuIndex < redis.lGetListSize("liku"); likuIndex++) {
                String liku = redis.lGetIndex("liku", likuIndex).toString();
                lukuSize[likuIndex] = liku;
            }
            System.err.println(Arrays.toString(lukuSize));
            //出仓
            Push.push(ResultUtil.success(ResultEnum.OUTWAREHOUSETwo, Arrays.toString(lukuSize)));
        }
    }

    /**
     * 握手时走这个方法，业务可以在这里获取cookie，request参数等
     */
    @Override
    public HttpResponse handshake(HttpRequest request, HttpResponse httpResponse, ChannelContext channelContext) {
        //存储绑定的通道
        String name = request.getParam("name");
        if (name != null) {
            //通过卡号来绑定用户
            Tio.bindGroup(channelContext, Const.GROUP_NAME);
            //存储绑定的通道
            TioMsgHandler.channelContext = channelContext;

        }
        return httpResponse;
    }

    /**
     * 获取在线人数
     *
     * @param httpRequest
     * @param httpResponse
     * @param channelContext
     * @throws Exception
     */
    @Override
    public void onAfterHandshaked(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
        int count = Tio.getAll(channelContext.tioConfig).getObj().size();
        log.info("{name:'admin',message:'" + channelContext.userid + " 进来了，共【" + count + "】人在线" + "'}");
    }

    /**
     * 字节消息（binaryType = arraybuffer）过来后会走这个方法
     */
    @Override
    public Object onBytes(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
        return null;
    }

    /**
     * 当客户端发close flag时，会走这个方法
     */
    @Override
    public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
        Tio.remove(channelContext, "receive close flag");
        return null;
    }

    /*
     * 字符消息（binaryType = blob）过来后会走这个方法
     */
    @Override
    public Object onText(WsRequest wsRequest, String text, ChannelContext channelContext) throws Exception {
        WsSessionContext wsSessionContext = (WsSessionContext) channelContext.get();
        HttpRequest httpRequest = wsSessionContext.getHandshakeRequest();//获取websocket握手包
        String clientIp = httpRequest.getClientIp();
        if (Objects.equals("getstore", text)) {
            try {
                log.info("接收的数据为：{}", text);
                Push.push(ResultUtil.success(ResultEnum.STEREOSCOPIC_WAREHOUSE, sw.selectAllTaskOccupy(new TProduct())));
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        } else if (text.startsWith("out")) { //出仓
            text = StringUtils.strip(text, "out");
            JSONObject json = JSONUtil.parseObj(text);
            Object code = json.get("code");
            if (code.equals(110)) {
                String data = json.get("data").toString();
                log.info("前端数据" + text);
                data = StringUtils.strip(data, "[]");
                String[] split = data.split(",");
                for (String value : split) {
                    state = 0;
                    if (value != null && value != "") {
                        if (redis.hasKey("liku")) {
                            likuSize = redis.lGetListSize("liku");
                            if (likuSize != 0) {
                                for (int likuIndex = 0; likuIndex < likuSize; likuIndex++) {
                                    if (value.equals(redis.lGetIndex("liku", likuIndex))) {
                                        state = 1;
                                    }
                                }
                            }
                            if (state != 1) {
                                redis.lSet("liku", value);
                            }
                        } else {
                            redis.lSet("liku", value);
                        }
                    }
                }
                outWarehouse();
                list.clear();
                tStereoscopicWarehouse = null;
                tsw = null;
            }
        } else if (Objects.equals("stop", text)) {  //停止
            redis.del("liku");
        } else if (Objects.equals("continue", text)) {  //继续
            result = true; //变为继续执行
            outWarehouse(); //继续
        } else if (Objects.equals("suspend", text)) {   //暂停
            result = false; //暂停
        } else if (text.startsWith("search")) { //搜索
            text = StringUtils.strip(text, "search");
            log.info("搜索" + text);
            TProduct tProduct = JSON.parseObject(text, TProduct.class);
            log.info("查询数据" + ResultUtil.success(ResultEnum.STEREOSCOPIC_WAREHOUSESELECT, sw.selectAllTaskOccupy(tProduct)));
            Push.push(ResultUtil.success(ResultEnum.STEREOSCOPIC_WAREHOUSESELECT, sw.selectAllTaskOccupy(tProduct)));
        } else if (text.startsWith("product-")) {  //一个字段查询
            text = StringUtils.strip(text, "product-");
            log.info("搜索一个值" + text);
            Push.push(ResultUtil.success(ResultEnum.STEREOSCOPIC_WAREHOUSESELECT, sw.selectByName(text)));
        } else if (text.startsWith("remark")) {
            text = StringUtils.strip(text, "remark");
            log.info("传过来的" + text);
            TWarehouse warehouse = JSON.parseObject(text, TWarehouse.class);
            log.info("解析对象" + warehouse);
            if (war.updateById(warehouse) > 0) {
                Push.push(ResultUtil.success(ResultEnum.UPDATEREMARK));
                log.info("修改成功！");
            } else {
                Push.push(ResultUtil.success(ResultEnum.UNKONW_ERROR));
                log.info("修改失败！");
            }

        }
        //返回值是要发送给客户端的内容，一般都是返回null
        return null;
    }

    public void outWarehouse() {  //出仓
        tStereoscopicWarehouse = sw.selectAllstatus(3);
        if (tStereoscopicWarehouse == null) {
            String likuValue = redis.lGetIndex("liku", 0).toString();
            if(likuValue!=null&&likuValue!=""){
                redis.lRemove("liku", 0, likuValue);
                tsw = sw.selectStereoscopicWarehouseById(Integer.valueOf(likuValue));
            }
            if (tsw != null) {
                //修改立体库位状态
                int rows = sw.updateStatusByBarcode(tsw.getBoxBarcode(), new Date());
                outSw = sw.selectOne(tsw.getBoxBarcode());
                //todo: 进行PLC发送出货
                Push.tcpPush(GlobalCall.str(outSw));
                log.info("发送给plc指令" + GlobalCall.str(outSw));
                //出仓
                Push.push(ResultUtil.success(ResultEnum.OUTWAREHOUSE, GlobalCall.str(outSw)));
                //封装参数
                outsw.insertOutWarehouseLog(new OutWarehouseLog(tsw, rows));
            }
        }
        if (likuSize!=0) {
            for (int likuIndex = 0; likuIndex < redis.lGetListSize("liku"); likuIndex++) {
                String liku = redis.lGetIndex("liku", likuIndex).toString();
                list.add(liku);
            }
        }

        log.info("缓存数据" + ResultUtil.success(ResultEnum.OUTWAREHOUSETwo, list) + "");
        //缓存的数据
        Push.push(ResultUtil.success(ResultEnum.OUTWAREHOUSETwo, list));
    }

}
